home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / cmds / pmake / customs / customslib.c < prev    next >
Encoding:
C/C++ Source or Header  |  1989-11-15  |  15.3 KB  |  555 lines

  1. /*-
  2.  * customslib.c --
  3.  *    Front end RPC stubs for clients of the customs daemons.
  4.  *
  5.  * Copyright (c) 1988, 1989 by the Regents of the University of California
  6.  * Copyright (c) 1988, 1989 by Adam de Boor
  7.  * Copyright (c) 1989 by Berkeley Softworks
  8.  *
  9.  * Permission to use, copy, modify, and distribute this
  10.  * software and its documentation for any non-commercial purpose
  11.  * and without fee is hereby granted, provided that the above copyright
  12.  * notice appears in all copies.  The University of California,
  13.  * Berkeley Softworks and Adam de Boor make no representations about
  14.  * the suitability of this software for any purpose.  It is provided
  15.  * "as is" without express or implied warranty.
  16.  */
  17. #ifndef lint
  18. static char *csid =
  19. "$Id: customslib.c,v 1.12 89/11/14 13:45:58 adam Exp $ SPRITE (Berkeley)";
  20. #endif lint
  21.  
  22. #include    "customs.h"
  23. #include    <sys/time.h>
  24. #include    <stdio.h>
  25. #include    <sys/file.h>
  26. #include    <netdb.h>
  27.  
  28. int                    customs_Socket = -1;
  29. struct sockaddr_in       customs_AgentAddr;
  30. struct timeval            customs_RetryTimeOut = {
  31.     CUSTOMS_RETRY, CUSTOMS_URETRY
  32. };
  33. static Rpc_Stat              lastStatus;
  34. static short                udpPort,
  35.                 tcpPort;
  36.  
  37. /*-
  38.  *-----------------------------------------------------------------------
  39.  * CustomsInit --
  40.  *    Initialize things so these functions may be used.
  41.  *
  42.  * Results:
  43.  *    None.
  44.  *
  45.  * Side Effects:
  46.  *    A udp socket is opened and customs_AgentAddr is initialized to be
  47.  *    suitable for talking to the local agent.
  48.  *
  49.  *-----------------------------------------------------------------------
  50.  */
  51. static void
  52. CustomsInit()
  53. {
  54.     struct servent  *sep;
  55.     int            i;
  56.  
  57.     i = 3;
  58.  
  59.     do {
  60.     sep = getservbyname("customs", "udp");
  61.     } while (sep == NULL && i-- > 0);
  62.  
  63.     if (sep == NULL) {
  64. #if 0
  65.     printf("customs/udp unknown\n");
  66.     /*XXX*/
  67.     exit(1);
  68. #else
  69.     udpPort = DEF_CUSTOMS_UDP_PORT;
  70. #endif
  71.     } else {
  72.     udpPort = sep->s_port;
  73.     }
  74.     i = 3;
  75.     do {
  76.     sep = getservbyname("customs", "tcp");
  77.     } while (sep == NULL && i-- > 0);
  78.  
  79.     if (sep == NULL) {
  80. #if 0
  81.     printf("customs/tcp unknown\n");
  82.     /*XXX*/
  83.     exit(1);
  84. #else
  85.     tcpPort = DEF_CUSTOMS_TCP_PORT;
  86. #endif
  87.     } else {
  88.     tcpPort = sep->s_port;
  89.     }
  90.     
  91.     customs_Socket = Rpc_UdpCreate(False, 0);
  92.     (void)fcntl(customs_Socket, F_SETFD, 1);
  93.     bzero(&customs_AgentAddr, sizeof(customs_AgentAddr));
  94.     customs_AgentAddr.sin_family = AF_INET;
  95.     customs_AgentAddr.sin_port = htons(udpPort);
  96.     customs_AgentAddr.sin_addr.s_addr = htons(INADDR_LOOPBACK);
  97. }
  98. /*-
  99.  *-----------------------------------------------------------------------
  100.  * Customs_Ping --
  101.  *    See if the local agent is alive.
  102.  *
  103.  * Results:
  104.  *    RPC_SUCCESS if the agent is alive and responding.
  105.  *
  106.  * Side Effects:
  107.  *    None.
  108.  *
  109.  *-----------------------------------------------------------------------
  110.  */
  111. Rpc_Stat
  112. Customs_Ping()
  113. {
  114.     if (customs_Socket == -1) {
  115.     CustomsInit();
  116.     }
  117.     lastStatus = Rpc_Call(customs_Socket, &customs_AgentAddr,
  118.               (Rpc_Proc)CUSTOMS_PING,
  119.               0, (Rpc_Opaque)0,
  120.               0, (Rpc_Opaque)0,
  121.               CUSTOMS_NRETRY, &customs_RetryTimeOut);
  122.     return(lastStatus);
  123. }
  124.  
  125. /*-
  126.  *-----------------------------------------------------------------------
  127.  * Customs_Host --
  128.  *    Request a host for exportation from the local agent. We send the
  129.  *    effective user-id partly because it's in the protocol and
  130.  *    partly because that's what determines file accesses...
  131.  *
  132.  * Results:
  133.  *    The status of the call. If RPC_SUCCESS, permitPtr contains the
  134.  *    agent's response, which may have an addr field of INADDR_ANY. This
  135.  *    indicates that a host could not be allocated.
  136.  *
  137.  * Side Effects:
  138.  *    None.
  139.  *
  140.  *-----------------------------------------------------------------------
  141.  */
  142. Rpc_Stat
  143. Customs_Host(flags, permitPtr)
  144.     short         flags;
  145.     ExportPermit  *permitPtr;
  146. {
  147.     Host_Data      data;
  148.     
  149.     data.uid = geteuid();
  150.     data.flags = flags;
  151.  
  152.     if (customs_Socket == -1) {
  153.     CustomsInit();
  154.     }
  155.     lastStatus = Rpc_Call(customs_Socket, &customs_AgentAddr,
  156.               (Rpc_Proc)CUSTOMS_HOST,
  157.               sizeof(data), (Rpc_Opaque)&data,
  158.               sizeof(ExportPermit), (Rpc_Opaque)permitPtr,
  159.               CUSTOMS_NRETRY, &customs_RetryTimeOut);
  160.     return(lastStatus);
  161. }
  162.  
  163. /*-
  164.  *-----------------------------------------------------------------------
  165.  * Customs_AvailInterval --
  166.  *    Set the interval at which the local agent informs the master of
  167.  *    its availability.
  168.  *
  169.  * Results:
  170.  *    The status of the call.
  171.  *
  172.  * Side Effects:
  173.  *    See above.
  174.  *
  175.  *-----------------------------------------------------------------------
  176.  */
  177. Rpc_Stat
  178. Customs_AvailInterval(interval)
  179.     struct timeval    *interval;
  180. {
  181.     if (customs_Socket == -1) {
  182.     CustomsInit();
  183.     }
  184.     lastStatus = Rpc_Call(customs_Socket, &customs_AgentAddr,
  185.               (Rpc_Proc)CUSTOMS_AVAILINTV,
  186.               sizeof(*interval), (Rpc_Opaque)interval,
  187.               0, (Rpc_Opaque)0,
  188.               CUSTOMS_NRETRY, &customs_RetryTimeOut);
  189.     return(lastStatus);
  190. }
  191.  
  192. /*-
  193.  *-----------------------------------------------------------------------
  194.  * Customs_Master --
  195.  *    Find the location of the current master customs agent.
  196.  *
  197.  * Results:
  198.  *    The status of the call. If the call succeeds, the passed
  199.  *    sockaddr_in is filled with address of the current master.
  200.  *
  201.  * Side Effects:
  202.  *    None.
  203.  *
  204.  *-----------------------------------------------------------------------
  205.  */
  206. Rpc_Stat
  207. Customs_Master(masterAddrPtr)
  208.     struct sockaddr_in    *masterAddrPtr;
  209. {
  210.     if (customs_Socket == -1) {
  211.     CustomsInit();
  212.     }
  213.     lastStatus = Rpc_Call(customs_Socket, &customs_AgentAddr,
  214.               (Rpc_Proc)CUSTOMS_MASTER,
  215.               0, (Rpc_Opaque)0,
  216.               sizeof(struct sockaddr_in),
  217.               (Rpc_Opaque)masterAddrPtr,
  218.               CUSTOMS_NRETRY, &customs_RetryTimeOut);
  219.     return(lastStatus);
  220. }
  221.  
  222. /*-
  223.  *-----------------------------------------------------------------------
  224.  * Customs_SetAvail --
  225.  *    Change the availability criteria for the local machine.
  226.  *
  227.  * Results:
  228.  *    The status of the call. If RPC_SUCCESS, criteria is overwritten
  229.  *    with the current/new criteria and criteria->changeMask contains
  230.  *    bits to indicate which, if any, values of the passed criteria
  231.  *    were out-of-bounds.
  232.  *
  233.  * Side Effects:
  234.  *    The criteria are changed if all are acceptable.
  235.  *
  236.  *-----------------------------------------------------------------------
  237.  */
  238. Rpc_Stat
  239. Customs_SetAvail(criteria)
  240.     Avail_Data      *criteria;
  241. {
  242.     if (customs_Socket == -1) {
  243.     CustomsInit();
  244.     }
  245.     lastStatus = Rpc_Call(customs_Socket, &customs_AgentAddr,
  246.               (Rpc_Proc)CUSTOMS_SETAVAIL,
  247.               sizeof(Avail_Data), (Rpc_Opaque)criteria,
  248.               sizeof(Avail_Data), (Rpc_Opaque)criteria,
  249.               CUSTOMS_NRETRY, &customs_RetryTimeOut);
  250.     return(lastStatus);
  251. }
  252.  
  253. /*-
  254.  *-----------------------------------------------------------------------
  255.  * Customs_Info --
  256.  *    Acquire information about the registered hosts from the master
  257.  *    agent at the given address.
  258.  *
  259.  * Results:
  260.  *    The status of the call. If RPC_SUCCESS, the passed buffer is filled
  261.  *    with information about the registered hosts.
  262.  *
  263.  * Side Effects:
  264.  *    Not really.
  265.  *
  266.  *-----------------------------------------------------------------------
  267.  */
  268. Rpc_Stat
  269. Customs_Info(masterAddrPtr, buf)
  270.     struct sockaddr_in    *masterAddrPtr;
  271.     char              buf[MAX_INFO_SIZE];
  272. {
  273.     if (customs_Socket == -1) {
  274.     CustomsInit();
  275.     }
  276.     lastStatus = Rpc_Call(customs_Socket, masterAddrPtr,
  277.               (Rpc_Proc)CUSTOMS_INFO,
  278.               0, (Rpc_Opaque)0,
  279.               MAX_INFO_SIZE, (Rpc_Opaque)buf,
  280.               CUSTOMS_NRETRY, &customs_RetryTimeOut);
  281.     return(lastStatus);
  282. }
  283.  
  284. /*-
  285.  *-----------------------------------------------------------------------
  286.  * Customs_PError --
  287.  *    Print error message based on last call.
  288.  *
  289.  * Results:
  290.  *    None.
  291.  *
  292.  * Side Effects:
  293.  *      A message is printed.
  294.  *
  295.  *-----------------------------------------------------------------------
  296.  */
  297. void
  298. Customs_PError(msg)
  299.     char          *msg;
  300. {
  301.     fprintf(stderr, "%s: %s\n", msg, Rpc_ErrorMessage(lastStatus));
  302. }
  303.  
  304. /*-
  305.  *-----------------------------------------------------------------------
  306.  * Customs_MakeWayBill --
  307.  *    Create a WayBill to be passed to the CUSTOMS_IMPORT function.
  308.  *
  309.  * Results:
  310.  *    Length of the buffer.
  311.  *
  312.  * Side Effects:
  313.  *    The passed buffer is overwritten.
  314.  *
  315.  *-----------------------------------------------------------------------
  316.  */
  317. int
  318. Customs_MakeWayBill(permitPtr, cwd, file, argv, environ, port, buf)
  319.     ExportPermit      *permitPtr; /* Permit for the job */
  320.     char              *cwd;        /* The current working directory */
  321.     char              *file;        /* File to execute */
  322.     char              **argv;        /* Arguments for it */
  323.     char              **environ;  /* Environment in which it should run */
  324.     unsigned short    port;        /* Port of udp socket for CUSTOMS_EXIT
  325.                      * return RPC call */
  326.     char              *buf;        /* Place to stuff the information */
  327. {
  328.     register char     *cp;
  329.     register int      i;
  330.     register WayBill    *wb;
  331.  
  332.     wb = (WayBill *)buf;
  333.     /*
  334.      * First the constant information:
  335.      *        - permit ID
  336.      *        - return call port
  337.      *        - real user id
  338.      *        - effective user id
  339.      *        - real group id
  340.      *        - effective group id
  341.      *        - array of groups process is in
  342.      *        - file creation mask
  343.      */
  344.     wb->id = permitPtr->id;
  345.     wb->port = port;
  346.     wb->ruid = getuid();
  347.     wb->euid = geteuid();
  348.     wb->rgid = getgid();
  349.     wb->egid = getegid();
  350.     wb->ngroups = getgroups(sizeof(wb->groups) / sizeof(int), wb->groups);
  351.     wb->umask = umask(0);
  352.     (void) umask(wb->umask);
  353.  
  354.     /*
  355.      * Then the variable-length part:
  356.      *        - the absolute path of the current working directory
  357.      *        - the file to execute (needn't be absolute)
  358.      *        - the number of arguments (stored on a longword boundary)
  359.      *        - the argument strings
  360.      *        - the number of environment strings (stored on a 32-bit boundary)
  361.      *        - the environment strings themselves
  362.      */
  363.     cp = (char *)&wb[1];
  364.     strcpy(cp, cwd);
  365.     cp += strlen(cp);
  366.     *cp++ = '\0';
  367.     strcpy(cp, file);
  368.     cp += strlen(file);
  369.     *cp++ = '\0';
  370.     cp = Customs_Align(cp, char *);
  371.  
  372.     for (i = 0; argv[i]; i++) {
  373.     ;
  374.     }
  375.     *(int *)cp = i;
  376.     cp += sizeof(int);
  377.     for (i = 0; argv[i]; i++) {
  378.     strcpy(cp, argv[i]);
  379.     cp += strlen(cp);
  380.     *cp++ = '\0';
  381.     }
  382.     cp = Customs_Align(cp, char *);
  383.     for (i = 0; environ[i]; i++) {
  384.     ;
  385.     }
  386.     *(int *)cp = i;
  387.     cp += sizeof(int);
  388.     for (i = 0; environ[i]; i++) {
  389.     strcpy(cp, environ[i]);
  390.     cp += strlen(cp);
  391.     *cp++ = '\0';
  392.     }
  393.     return (cp - buf);
  394. }
  395.  
  396. /*-
  397.  *-----------------------------------------------------------------------
  398.  * Customs_RawExport --
  399.  *    Start a job running on another machine, but don't fork an
  400.  *    "export" job to handle it -- just return the tcp socket open
  401.  *    to the remote job, or -1 if the job could not be exported.
  402.  *
  403.  * Results:
  404.  *    socket to remote job if ok. If < 0, value is:
  405.  *        -100    Couldn't find host
  406.  *        -101    Couldn't create return socket
  407.  *        -102    Couldn't get name of return socket
  408.  *        -104    Remote side refused import
  409.  *       <-200    -(result+200) gives the return status from the
  410.  *            CUSTOMS_IMPORT call.
  411.  *    This is hokey, but was done quickly to provide debugging info in
  412.  *    pmake.
  413.  *
  414.  * Side Effects:
  415.  *
  416.  *-----------------------------------------------------------------------
  417.  */
  418. int
  419. Customs_RawExport(file, argv, cwd, flags, retSockPtr, permitPtr)
  420.     char          *file;            /* File to exec */
  421.     char          **argv;           /* Arguments to give it */
  422.     char          *cwd;                /* Current directory. NULL if not
  423.                      * determined */
  424.     int              flags;         /* Flags to pass to Customs_Host */
  425.     int              *retSockPtr;        /* Socket on which return call should be
  426.                      * made when process exits. If < 0, will
  427.                      * return a socket for the purpose. */
  428.     ExportPermit  *permitPtr;        /* OUT: permit returned by agent */
  429. {
  430.     extern char       **environ;  /* Current process environment */
  431.     int                  sock;        /* TCP socket connecting to exported
  432.                      * process */
  433.     struct sockaddr_in     importServer;    /* Address of server running our
  434.                      * process */
  435.     char              msg[128];   /* Error message from import server */
  436.     Rpc_Stat          rstat;        /* Return status from RPC calls */
  437.     char              buf[MAX_DATA_SIZE]; /* Buffer for outgoing waybill */
  438.     int                  buflen;        /* Length of buffer */
  439.     char              loccwd[MAXPATHLEN]; /* Place to stuff cwd if not
  440.                          * given */
  441.     struct timeval    timeout;    /* Timeout for IMPORT request (since it's
  442.                      * TCP, there's a different timeout than
  443.                      * normal Customs calls) */
  444.     u_short           retPort;    /* Port number of return call socket for
  445.                      * import server to return the process'
  446.                      * exit status */
  447.     Boolean           ourSock;    /* True if we allocated the return call
  448.                      * socket */
  449.     ExportPermit      locPermit;  /* Local permit if the caller isn't
  450.                      * interested */
  451.  
  452.     if (permitPtr == (ExportPermit *)NULL) {
  453.     permitPtr = &locPermit;
  454.     }
  455.     /*
  456.      * Find out where we may go, first.
  457.      */
  458.     rstat = Customs_Host(flags, permitPtr);
  459.     if (rstat != RPC_SUCCESS) {
  460.     return (-(int)rstat);
  461.     } else if (CUSTOMS_FAIL(&permitPtr->addr)) {
  462.     return(CUSTOMS_NOEXPORT);
  463.     }
  464.     /*
  465.      * We have somewhere to go. Now we need to set up the return-call
  466.      * socket so we can pass its port number to the import server. If the
  467.      * caller already has a socket in mind, ourSock is set False.
  468.      */
  469.     if (*retSockPtr < 0) {
  470.     ourSock = True;
  471.     *retSockPtr = Rpc_UdpCreate(True, 0);
  472.     if (*retSockPtr < 0) {
  473.         return(CUSTOMS_NORETURN);
  474.     }
  475.     } else {
  476.     ourSock = False;
  477.     }
  478.     
  479.     /*
  480.      * Figure out the port number. If this fails, we can't export...
  481.      */
  482.     buflen = sizeof(importServer);
  483.     if (getsockname(*retSockPtr, &importServer, &buflen) < 0) {
  484.     if (ourSock) {
  485.         (void) close(*retSockPtr);
  486.     }
  487.     return (CUSTOMS_NONAME);
  488.     }
  489.     retPort = importServer.sin_port;
  490.     
  491.     /*
  492.      * Create the TCP socket for talking to the remote process and set up
  493.      * the address of the remote server for doing the RPC
  494.      */
  495.     sock = Rpc_TcpCreate(False, 0);
  496.     if (sock < 0) {
  497.     if (ourSock) {
  498.         (void) close(*retSockPtr);
  499.     }
  500.     return(CUSTOMS_NOIOSOCK);
  501.     }
  502.     importServer.sin_family = AF_INET;
  503.     importServer.sin_port = htons(tcpPort);
  504.     importServer.sin_addr = permitPtr->addr;
  505.  
  506.     /*
  507.      * If they haven't already figured out the current working directory,
  508.      * we have to do it for them.
  509.      */
  510.     if (cwd == (char *)NULL) {
  511.     getwd(loccwd);
  512.     cwd = loccwd;
  513.     }
  514.  
  515.     /*
  516.      * Using all this information, create a WayBill buffer to pass to
  517.      * the server.
  518.      */
  519.     buflen = Customs_MakeWayBill(permitPtr, cwd, file, argv, environ,
  520.                  retPort, buf);
  521.     /*
  522.      * Call the server. We only send one message, since TCP is "reliable".
  523.      * If we don't get a response in 20 seconds, the export failed.
  524.      */
  525.     timeout.tv_sec = 20;
  526.     timeout.tv_usec = 0;
  527.     rstat = Rpc_Call(sock, &importServer, (Rpc_Proc)CUSTOMS_IMPORT,
  528.              buflen, (Rpc_Opaque)buf,
  529.              sizeof(msg), (Rpc_Opaque)msg,
  530.              1, &timeout);
  531.     lastStatus = rstat;
  532.     /*
  533.      * There are two ways an IMPORT call may fail -- if the server is down,
  534.      * we'll get a RPC error code. If the server denies permission to export,
  535.      * for some reason, it'll return some message other than "Ok".
  536.      * In both cases, we clean up and return < 0 to indicate failure.
  537.      */
  538.     if (rstat != RPC_SUCCESS) {
  539.     if (ourSock) {
  540.         (void)close(*retSockPtr);
  541.     }
  542.     (void)close(sock);
  543.     return (-200-(int)rstat);
  544.     } else if (strcmp(msg, "Ok") == 0) {
  545.     return (sock);
  546.     } else {
  547.     fprintf(stderr, "CUSTOMS_IMPORT: %s\n", msg);
  548.     if (ourSock) {
  549.         (void)close(*retSockPtr);
  550.     }
  551.     (void) close(sock);
  552.     return (CUSTOMS_ERROR);
  553.     }
  554. }
  555.